//-------------------------------------------------------------------
//	Copyright (c) 2013  Zhirnov Andrey
//	This file is part of the "Noise Library" project.
//	See copyright notice in "linNoiseCL.h".
//-------------------------------------------------------------------

#pragma once

#include "../CSource.h"
#include "GeneratorUtils.h"
#include "GeneratorNativeUtils.h"

namespace Noise
{
	
	//
	// Function Source for Checkerboard pattern.
	//

	class CSourceCheckerboard : public CSource
	{
	// types
	protected:
		typedef CSourceCheckerboard	Self;


	// variables
	protected:
		static const
			ESource		_sourceType = CHECKERBOARD;


	// methods
	public:
		CSourceCheckerboard ()
		{}

		~CSourceCheckerboard ()
		{}

		ESourceState GetState () const
		{
			return SOURCE_COMPLETE;
		}
		
		virtual void Delete ()
		{
		}

		virtual EResult GetInteger (ESourceQuery type, int *v, int count) const
		{
			CHECK_ARGUMENT_R( count >= 1, INVALID_VALUE );

			switch ( type )
			{
				case SOURCE_STATE :
					v[0] = GetState();
					return OK;

				case SOURCE_TYPE :
					v[0] = _sourceType;
					return OK;

				case SOURCES_COUNT :
					v[0] = 1;
					return OK;

				case INPUT_SOURCES :
					v[0] = 0;
					return OK;
			}
			return INVALID_ENUM;
		}
		
		virtual CSourcePtr Clone () const override
		{
			return new Self();
		}
		
		virtual void PreBuild (const TPreBuildData &data) override
		{
		}

		virtual bool BuildFunction (TFunctionData &data) override
		{
			Utils::NoiseGenFunctions( data );

			CSource::BuildFunctionHeader( data.source, _id )
				<< TOSTRING(
					(( (int)( floor( MakeInt32Range(vPoint.x) ) ) & 1 ^
					   (int)( floor( MakeInt32Range(vPoint.y) ) ) & 1 ^
					   (int)( floor( MakeInt32Range(vPoint.z) ) ) & 1 ) ? -1.0 : 1.0 )\n
				);

			return true;
		}
		
		NATIVE(
		template < typename Real, Real (CSource::*NativeFunction)(const TVec<Real,3> &) >
		Real NativeFunction (const TVec<Real,3> &vPoint)
		{
			using namespace NativeUtils;
			
			int ix = (int)( Floor( MakeInt32Range(vPoint.x) ) );
			int iy = (int)( Floor( MakeInt32Range(vPoint.y) ) );
			int iz = (int)( Floor( MakeInt32Range(vPoint.z) ) );
			return Real( (ix & 1 ^ iy & 1 ^ iz & 1) ? -1.0 : 1.0 );
		}

		virtual float32 NativeFunction32 (const fvec3 &vPoint) override
		{
			return NativeFunction< float32, &CSource::NativeFunction32 >( vPoint );
		}

		virtual float64 NativeFunction64 (const dvec3 &vPoint) override
		{
			return NativeFunction< float64, &CSource::NativeFunction64 >( vPoint );
		})

		static bool CreateSource (CSourcePtr &src, CContext *context, ESource type)
		{
			ASSERT( type == _sourceType );

			src = new Self();
			return true;
		}
	};

}	// Noise